鐵人賽最大的噩夢不是寫不出東西、或寫不好,而是一不小心回到上一頁卻沒存檔。(爛Apple滑鼠!)
產生UI畫面或啟動一個APP需要Widget。
但到底什麼是Widget?一個APP跟一個UI概念上是差很多的東西才對,怎麼可能混用呢?
這要回頭說說物件導向。
(以下需要搭配SDK建立的基本範例程式。在Day 5。)
void main() {
runApp(MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page')
));
}
因為物件導向是要讓人用現實世界的體驗與思維去設計程式,所以用現實世界的事物做例子吧!
假設MaterialApp(用來啟動APP所需要的物件)是鳥類,那MyHomePage就是靈長類,而Widget就是動物。
鳥類是種動物,靈長類也是種動物,MaterialApp是種Widget,MyHomePage也是種Widget。
相較於鳥類的概念,動物的概念當然簡單許多,但動物有的概念在鳥類也都一併俱全。
這就好像程式碼的資料欄位與函數一樣,動物有的資料欄位與函數,鳥類也都一併俱全。(這話內容有些地方需要商確,雖然概念可行,但不精準。)
一個APP要用來輸出畫面、或建立一個可運作的環境,需要的資料與功能在建立環境或輸出畫面來說有某些共通之處,所以就用Widget來作為建立這個共通之處的基礎,以這個基礎再去發展出各種具備特殊功能、可以應用在系統更深入之處的Widget。
所以如果高興,可以使用直接將MyHomePage交由runApp執行,程式可以順利啟動,但APP會告訴你這個Widget缺少它執行所需要的功能。
先不去糾結為什麼、或該怎麼做,讓一個像Widget這樣的「概念」被完整擴展為MaterialApp這類「實物」,這個過程在物件導向中稱為繼承。
MaterialAPP繼承了Widget。
鳥類繼承了動物。
但實際上要做這個流程,用個簡單的A/B物件做範例好了...
class A{
String name;
void getName(String n){
name = n;
}
}
可以看出來A物件擁有「被命名」的特性。(當物件會被產生大量資料時,如何知道「目前程式正在操作哪一筆資料」很重要,方法之一就是將每筆資料命名。)
但如果我想要我的資料可以「向UI介面輸出資料的名稱」時,我就可以考慮繼承A物件來產生B物件。
(為什麼要輸出?也許程式發生了錯誤,可以讓使用者知道錯誤類別、發生在哪筆資料上。)
class B extends A{
void showName(UI ui){
...
}
}
「extends A」就是讓B物件去繼承A物件、擁有A物件的欄位屬性。
「showName」是個新增的函數,內容可以在設計B物件時完全獨立設計和思考,但如果A物件已經有的函數內容令我不滿意時,該怎麼辦呢?
答案是...修改它。用B物件繼續做範例吧!產生一個C物件來修改「showName」。
class C extends B{
int count;
@override
void showName(UI ui){
super.showName(ui);
giveName(name + ' ' + count);
}
}
「super」是指「該物件(C)所繼承的物件(B)」,「super.函數」就是指「所繼承的物件的函數」。
這樣做的C物件的「showName」會完整擁有B物件的「showName」,但又有自己獨特增加的功能。如果不希望這樣做、想要整個放棄掉B物件的「showName」,只要拿掉「super.showName」就好。
修改一個函數的內容,這種行為又稱為「擴充」。
被擴充的函數會在上面標記「@override」。這種用「@」開頭的指令通常被稱為Annotation,使用或設計它也是種程式設計領域的技巧。
像這樣,確立一件事情,例如Widget,例如「命名」「報名」,然後重複使用這件事情去建立各種功能,例如建立各種Widget或資料物件,這就可以稱為模組。
但,是「這件事情」是模組?還是「重複使用這件事情所建立的東西是模組」?這方面的定義我覺得有點曖昧。
反正有了一個模組後,我們可以有另一個模組,例如怎麼使用Widget?例如怎麼「去命名」?
以使用Widget來說,runApp就是個模組提供的功能,MaterialApp內有「home」欄位去接收另一個「Widget」後產生畫面就是個模組提供的功能。
這都是個「接收Widget」的模組,但實際上卻做了差異很大的事情。
好多個模組組合起來,就是框架。
我一向覺得這類名詞很空洞很繁雜,但它的定義又有明確的差異,用來溝通似乎很精準,像如果有某人說「這是我寫的一套框架」,那你就可以預期裡面有多個模組,這些模組不一定都是某人自己寫的,也可能是他使用其他人完成的模組,這會延伸很多問題.....
「這些模組有沒有可能有Bug?」「如果有Bug要怎麼修正?」「我可以抽換掉這些模組嗎?(例如改用同一套模組、但卻是不同版本?)」「既然是框架,那一定是有點規模的程式碼了?」
所以也不能說這些名詞毫無用途。